﻿using System;
using System.Security.Cryptography;

namespace Xenta.Utils
{
    /// <summary>
    /// Represents the math helper.
    /// </summary>
    public static class MathHelper
    {
        #region Methods

        /// <summary>
        /// Generates the random number.
        /// </summary>
        /// <returns>The randomly generated number.</returns>
        public static uint RandomNumber()
        {
            return RandomNumber(0xffffffff);
        }

        /// <summary>
        /// Generates the random number.
        /// </summary>
        /// <param name="andMask">The AND mask.</param>
        /// <returns>The randomly generated number.</returns>
        public static uint RandomNumber(uint andMask)
        {
            return RandomNumber(andMask, 0x00000000);
        }

        /// <summary>
        /// Generates the random number.
        /// </summary>
        /// <param name="andMask">The AND mask.</param>
        /// <param name="orMask">The OR mask.</param>
        /// <returns>The randomly generated number.</returns>
        public static uint RandomNumber(uint andMask, uint orMask)
        {
            return RandomNumber(andMask, orMask, 0x00000000);
        }

        /// <summary>
        /// Generates the random number.
        /// </summary>
        /// <param name="andMask">The AND mask.</param>
        /// <param name="orMask">The OR mask.</param>
        /// <param name="xorMask">The XOR mask.</param>
        /// <returns>The randomly generated number.</returns>
        /// <example>
        /// // Will return unsigned integer where the value will be in range between 8192(0x00002000) and 9192(0x000023e8).
        /// MathHelper.RandomNumber(0x000003e8, 0x00002000, 0x00000000)
        /// // Will return integer where the value will be in range between -8192(0xffffe000) and -9192(0xffffdc18).
        /// (int)MathHelper.RandomNumber(0x000003e8, 0x00002000, 0xffffffff)
        /// </example>
        public static uint RandomNumber(uint andMask, uint orMask, uint xorMask)
        {
            uint num = 0;

            using(var csp = new RNGCryptoServiceProvider())
            {
                var buf = new byte[4];

                csp.GetNonZeroBytes(buf);

                num = BitConverter.ToUInt32(buf, 0);
                num = ((num & andMask) | orMask) ^ xorMask;
            }
            return num;
        }

        /// <summary>
        /// Converts the decimal value from a source ratio to the target ratio.
        /// </summary>
        /// <param name="value">The decimal value.</param>
        /// <param name="srcRatio">The source ratio.</param>
        /// <param name="tgtRatio">The target rate.</param>
        /// <returns>The converted value.</returns>
        public static decimal Ratio(decimal value, decimal srcRatio, decimal tgtRatio)
        {
            if(srcRatio == tgtRatio)
            {
                return value;
            }

            double dblValue = (double)value;
            double dblSrcRatio = (double)srcRatio;
            double dblTgtRatio = (double)tgtRatio;

            return (decimal)((dblValue * dblSrcRatio) / dblTgtRatio);
        }

        #endregion
    }
}
